package cn.kgc.tangcco.service.impl;

import cn.kgc.tangcco.pojo.Idiom;
import cn.kgc.tangcco.service.IdiomService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestOperations;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Future;

/**
 * @author 李昊哲
 * @Description
 * @create 2021/2/4 17:17
 */
@Service
public class IdiomServiceImpl implements IdiomService {
    private final RestOperations restTemplate;
    private static ObjectMapper objectMapper = new ObjectMapper();

    public IdiomServiceImpl(RestOperations restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Override
    public List<Idiom> findByIds(List<Integer> ids) throws JsonProcessingException {
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity<String> requestEntity = new HttpEntity<>(objectMapper.writeValueAsString(ids), headers);
        String url = "http://idiom-provider/idiom/findByIds";
        //  执行HTTP请求
        ResponseEntity<Idiom[]> responseEntity = restTemplate.postForEntity(url, requestEntity, Idiom[].class);
        Idiom[] idioms = responseEntity.getBody();
        List<Idiom> idiomList = Arrays.asList(idioms);
        //  输出结果
        return idiomList;
    }

    @HystrixCommand(groupKey = "idiom-provider-singlepool",
            commandKey = "selectById",
            threadPoolKey = "idiom-provider-singlepool",
            commandProperties = {
                    @HystrixProperty(name = "execution.isolation.thread.tiomeoutInMillseconds",value="5000")
            },
            threadPoolProperties = {
                    // 线程池大小
                    @HystrixProperty(name = "coreSize",value = "3"),
                    // 队列等待阈值(最大队列长度 ,默认 -1)
                    @HystrixProperty(name = "maxQueueSize",value = "100"),
                    // 线程存活时间 默认1分钟
                    @HystrixProperty(name = "keepAliveTimeMinutes",value = "2"),
                    // 超出队列制定拒绝策略
                    @HystrixProperty(name = "queueSizeRejectionThreshold",value = "100")
            }
    )
    @Override
    public Idiom selectById(Integer id) {
        System.out.println(Thread.currentThread().getName());
        String url = "http://idiom-provider/idiom/findById/" + id;
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        MultiValueMap<String, Integer> params = new LinkedMultiValueMap<>();
        HttpEntity<MultiValueMap<String, Integer>> requestEntity = new HttpEntity<>(params, headers);
        //  执行HTTP请求
        ResponseEntity<Idiom> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, new ParameterizedTypeReference<>() {
        });
        //  输出结果
        return response.getBody();
    }

    @HystrixCommand(groupKey = "idiom-provider-pagepool",
                    commandKey = "finAllByLoadBalancerClientAnnotation",
                    threadPoolKey = "idiom-provider-pagepool",
                    commandProperties = {
                        @HystrixProperty(name = "execution.isolation.thread.tiomeoutInMillseconds",value="5000")
                    },
                    threadPoolProperties = {
                        // 线程池大小
                        @HystrixProperty(name = "coreSize",value = "6"),
                        // 队列等待阈值(最大队列长度 ,默认 -1)
                        @HystrixProperty(name = "maxQueueSize",value = "100"),
                        // 线程存活时间 默认1分钟
                        @HystrixProperty(name = "keepAliveTimeMinutes",value = "2"),
                        // 超出队列制定拒绝策略
                        @HystrixProperty(name = "queueSizeRejectionThreshold",value = "100")
                    }
                    ,fallbackMethod = "finAllByLoadBalancerClientAnnotationFallback"
    )
    @Override
    public String finAllByLoadBalancerClientAnnotation(Integer page, Integer limit) {
        String url = "http://idiom-provider/idiom/findAllWithPostForm";
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        MultiValueMap<String, Integer> params = new LinkedMultiValueMap<>();
        //  也支持中文
        params.add("page", page);
        params.add("limit", limit);
        HttpEntity<MultiValueMap<String, Integer>> requestEntity = new HttpEntity<>(params, headers);
        //  执行HTTP请求
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, new ParameterizedTypeReference<>() {
        });
        //  输出结果
        return response.getBody();
    }

    public String finAllByLoadBalancerClientAnnotationFallback() {
        String url = "http://idiom-provider/idiom/findAllWithPostForm";
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        MultiValueMap<String, Integer> params = new LinkedMultiValueMap<>();
        //  也支持中文
        params.add("page", 1);
        params.add("limit", 5);
        HttpEntity<MultiValueMap<String, Integer>> requestEntity = new HttpEntity<>(params, headers);
        //  执行HTTP请求
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, new ParameterizedTypeReference<>() {
        });
        //  输出结果
        return response.getBody();
    }
}
